﻿Namespace Functions
    Public Class MetisRefFunction
        Implements IMetisCommonEntity

        Private _MetisCore As MetisCore

        Private _ID As Integer
        Private _Alias As String
        Private _Position As System.Drawing.Point
        Private _OwningFunction As MetisResultFunction
        Private _ReferencedFunction As MetisFunction

        Private _BackupAlias As String
        Private _BackupPosition As System.Drawing.Point

        Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged

        Sub New(ByVal MetisCore As Core.MetisCore, ByVal Owner As MetisResultFunction, ByVal RefFunction As MetisFunction)
            _MetisCore = MetisCore
            _OwningFunction = Owner
            _ReferencedFunction = RefFunction
            _ID = _MetisCore.GetTemporaryID
            _Alias = CreateDefaultAlias
            Dim tmpXPos As Integer = 0
            Dim tmpYPos As Integer = 0

            For Each item As MetisRefFunction In _OwningFunction.FunctionReferences
                If item.Position.X > tmpXPos Then
                    tmpXPos = item.Position.X
                    tmpYPos = item.Position.Y
                End If
            Next
            _Position = New System.Drawing.Point(tmpXPos + 16, tmpYPos + 16)
            _BackupPosition = New System.Drawing.Point(tmpXPos + 16, tmpYPos + 16)

        End Sub

        Sub New(ByVal MetisCore As Core.MetisCore, ByVal Owner As MetisResultFunction, ByVal RefFunction As MetisFunction, ByVal Position As System.Drawing.Point)
            Me.New(MetisCore, Owner, RefFunction)
            _Position = Position
            _BackupPosition = New System.Drawing.Point(Position.X, Position.Y)
        End Sub

        Sub New(ByVal MetisCore As Core.MetisCore, ByVal Owner As MetisResultFunction, ByVal FuncRefID As Integer, ByVal RefFunction As MetisFunction, ByVal Position As System.Drawing.Point, ByVal [Alias] As String)
            Me.New(MetisCore, Owner, RefFunction, Position)
            _ID = FuncRefID
            _Alias = [Alias]
            _BackupAlias = [Alias]
        End Sub

        Public Function CreateDefaultAlias() As String
            Dim tmpAlias As String = _ReferencedFunction.Name
            Dim i As Integer = 0
            Dim tmpFuncRef As MetisRefFunction = _OwningFunction.FunctionReferences.Find(tmpAlias)
            Do While tmpFuncRef IsNot Nothing AndAlso Not Me.Equals(tmpFuncRef)
                i += 1
                tmpAlias = String.Format("{0}_{1:D2}", _ReferencedFunction.Name.Substring(0, Math.Min(_ReferencedFunction.Name.Length, Core.MetisCore.MAX_NAME_LENGTH - 3)), i)
                tmpFuncRef = _OwningFunction.FunctionReferences.Find(tmpAlias)
            Loop
            Return tmpAlias
        End Function

        Public Function GetNextID() As Integer Implements IMetisCommonEntity.GetNextID
            _ID = _MetisCore.GetNextID
            RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("ID"))
            Return _ID
        End Function

        Public ReadOnly Property ID() As Integer Implements IMetisCommonEntity.ID
            Get
                Return _ID
            End Get
        End Property

        Public Property [Alias]() As String Implements IMetisCommonEntity.Name
            Get
                Return _Alias
            End Get
            Set(ByVal value As String)
                If MetisCore.IsValidFieldName(value, Core.MetisCore.MAX_NAME_LENGTH) Then
                    For Each item As MetisRefFunction In _OwningFunction.FunctionReferences
                        If Not Me.Equals(item) AndAlso value.Equals(item.Alias, StringComparison.OrdinalIgnoreCase) Then
                            Throw New Exceptions.DublicateNameException(value)
                        End If
                    Next
                    _Alias = value
                    RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("Alias"))
                Else
                    Throw New Exceptions.InvalidNameException(value)
                End If
            End Set
        End Property

        Public Property Annotation() As String Implements IMetisCommonEntity.Annotation
            Get
                Return _ReferencedFunction.Annotation
            End Get
            Set(ByVal value As String)
                Throw New InvalidOperationException()
            End Set
        End Property

        Public Property Position() As System.Drawing.Point
            Get
                Return _Position
            End Get
            Set(ByVal value As System.Drawing.Point)
                _Position = value
                RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs("Position"))
            End Set
        End Property

        Public Function CompareTo(ByVal other As IMetisCommonEntity) As Integer Implements System.IComparable(Of IMetisCommonEntity).CompareTo
            Return (String.Compare(_Alias, other.Name, True) Or _ID = other.ID)
        End Function

        Public ReadOnly Property OwningFunction() As MetisResultFunction
            Get
                Return _OwningFunction
            End Get
        End Property

        Public ReadOnly Property ReferencedFunction() As MetisFunction
            Get
                Return _ReferencedFunction
            End Get
        End Property

    End Class

End Namespace

